home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 90 / CD Actual 90.iso / Software3D / K-3D / k3d-0.4.2.1 / shaders / k3d_patterns.h < prev    next >
Encoding:
C/C++ Source or Header  |  2004-07-23  |  7.1 KB  |  254 lines

  1. /************************************************************************
  2.  * patterns.h - Some handy functions for various patterns.  Wherever
  3.  *              possible, antialiased versions will also be given.
  4.  *
  5.  * Author: Larry Gritz (gritzl@acm.org)
  6.  *
  7.  * Reference:
  8.  *   _Advanced RenderMan: Creating CGI for Motion Picture_, 
  9.  *   by Anthony A. Apodaca and Larry Gritz, Morgan Kaufmann, 1999.
  10.  *
  11.  * $Revision: 1.1 $    $Date: 2002/11/25 20:37:34 $
  12.  *
  13.  ************************************************************************/
  14.  
  15.  
  16.  
  17. #ifndef PATTERNS_H
  18. #define PATTERNS_H 1
  19.  
  20. #include "k3d_filterwidth.h"
  21.  
  22.  
  23.  
  24. /* Handy square routine */
  25. float sqr (float x)
  26. {
  27.     return x*x;
  28. }
  29.  
  30.  
  31.  
  32. /* Antialiased abs().  
  33.  * Compute the box filter of abs(t) from x-dx/2 to x+dx/2.
  34.  * Hinges on the realization that the indefinite integral of abs(x) is 
  35.  * sign(x) * 1/2 x*x;
  36.  */
  37. float filteredabs (float x, dx)
  38. {
  39.     float integral (float t) {
  40.     return sign(t) * 0.5 * t*t;
  41.     }
  42.  
  43.     float x0 = x - 0.5*dx;
  44.     float x1 = x0 + dx;
  45.     return (integral(x1) - integral(x0)) / dx;
  46. }
  47.  
  48.  
  49.  
  50.  
  51. /* Antialiased smoothstep(e0,e1,x).  
  52.  * Compute the box filter of smoothstep(e0,e1,t) from x-dx/2 to x+dx/2.
  53.  * Strategy: divide domain into 3 regions: t < e0, e0 <= t <= e1,
  54.  * and t > e1.  Region 1 has integral 0.  Region 2 is computed by
  55.  * analytically integrating smoothstep, which is -2t^3+3t^2.  Region 3
  56.  * is trivially 1.
  57.  */
  58. float filteredsmoothstep (float e0, e1, x, dx)
  59. {
  60.     float integral (float t) {
  61.     return -0.5*t*t * (t*t + t);
  62.     }
  63.  
  64.     /* Compute x0, x1 bounding region of integration, and normalize so that
  65.      * e0==0, e1==1
  66.      */
  67.     float edgediff = e1 - e0;
  68.     float x0 = (x-e0)/edgediff;
  69.     float fw = dx / edgediff;
  70.     x0 -= 0.5*fw;
  71.     float x1 = x0 + fw;
  72.  
  73.     /* Region 1 always contributes nothing */
  74.     float int = 0;
  75.     /* Region 2 - compute integral in region between 0 and 1 */
  76.     if (x0 < 1 && x1 > 0)
  77.     int += integral(min(x1,1)) - integral(max(x0,0));
  78.     /* Region 3 - is 1.0 */
  79.     if (x1 > 1)
  80.     int += x1-max(1,x0);
  81.     return int / fw;
  82. }
  83.  
  84.  
  85.  
  86. /* A 1-D pulse pattern:  return 1 if edge0 <= x <= edge1, otherwise 0 */
  87. float pulse (float edge0, edge1, x)
  88. {
  89.     return step(edge0,x) - step(edge1,x);
  90. }
  91.  
  92.  
  93.  
  94. float filteredpulse (float edge0, edge1, x, dx)
  95. {
  96.     float x0 = x - dx/2;
  97.     float x1 = x0 + dx;
  98.     return max (0, (min(x1,edge1)-max(x0,edge0)) / dx);
  99. }
  100.  
  101.  
  102.  
  103. /* A pulse train: a signal that repeats with a given period, and is
  104.  * 0 when 0 <= mod(x,period) < edge, and 1 when mod(x,period) > edge.
  105.  */
  106. float pulsetrain (float edge, period, x)
  107. {
  108.     return pulse (edge, period, mod(x,period));
  109. }
  110.  
  111.  
  112. /* Filtered pulse train: it's not as simple as just returning the mod
  113.  * of filteredpulse -- you have to take into account that the filter may
  114.  * cover multiple pulses in the train.
  115.  * Strategy: consider the function that is the integral of the pulse
  116.  * train from 0 to x. Just subtract!
  117.  */
  118. float filteredpulsetrain (float edge, period, x, dx)
  119. {
  120.     /* First, normalize so period == 1 and our domain of interest is > 0 */
  121.     float w = dx/period;
  122.     float x0 = x/period - w/2;
  123.     float x1 = x0+w;
  124.     float nedge = edge / period;   /* normalized edge value */
  125.  
  126.     /* Definite integral of normalized pulsetrain from 0 to t */
  127.     float integral (float t) { 
  128.         extern float nedge;
  129.         return ((1-nedge)*floor(t) + max(0,t-floor(t)-nedge));
  130.     }
  131.  
  132.     /* Now we want to integrate the normalized pulsetrain over [x0,x1] */
  133.     return (integral(x1) - integral(x0)) / w;
  134. }
  135.  
  136.  
  137.  
  138. float
  139. smoothpulse (float e0, e1, e2, e3, x)
  140. {
  141.     return smoothstep(e0,e1,x) - smoothstep(e2,e3,x);
  142. }
  143.  
  144.  
  145. float
  146. filteredsmoothpulse (float e0, e1, e2, e3, x, dx)
  147. {
  148.     return filteredsmoothstep(e0,e1,x,dx) - filteredsmoothstep(e2,e3,x,dx);
  149. }
  150.  
  151.  
  152.  
  153. /* A pulse train of smoothsteps: a signal that repeats with a given
  154.  * period, and is 0 when 0 <= mod(x/period,1) < edge, and 1 when
  155.  * mod(x/period,1) > edge.  
  156.  */
  157. float smoothpulsetrain (float e0, e1, e2, e3, period, x)
  158. {
  159.     return smoothpulse (e0, e1, e2, e3, mod(x,period));
  160. }
  161.  
  162.  
  163.  
  164. /* varyEach takes a computed color, then tweaks each indexed item
  165.  * separately to add some variation.  Hue, saturation, and lightness
  166.  * are all independently controlled.  Hue adds, but saturation and
  167.  * lightness multiply.
  168.  */
  169. color varyEach (color Cin; float index, varyhue, varysat, varylum;)
  170. {
  171.     /* Convert to "hsl" space, it's more convenient */
  172.     color Chsl = ctransform ("hsl", Cin);
  173.     float h = comp(Chsl,0), s = comp(Chsl,1), l = comp(Chsl,2);
  174.     /* Modify Chsl by adding Cvary scaled by our separate h,s,l controls */
  175.     h += varyhue * (cellnoise(index+3)-0.5);
  176.     s *= 1 - varysat * (cellnoise(index-14)-0.5);
  177.     l *= 1 - varylum * (cellnoise(index+37)-0.5);
  178.     Chsl = color (mod(h,1), clamp(s,0,1), clamp(l,0,1));
  179.     /* Clamp hsl and transform back to rgb space */
  180.     return ctransform ("hsl", "rgb", clamp(Chsl,color 0, color 1));
  181. }
  182.  
  183.  
  184.  
  185. /* Given 2-D texture coordinates ss,tt and their filter widths ds, dt,
  186.  * and the width and height of the grooves between tiles (assuming that
  187.  * tile spacing is 1.0), figure out which (integer indexed) tile we are
  188.  * on and what coordinates (on [0,1]) within our individual tile we are
  189.  * shading.
  190.  */
  191. float
  192. tilepattern (float ss, tt, ds, dt;
  193.          float groovewidth, grooveheight;
  194.          output float swhichtile, twhichtile;
  195.          output float stile, ttile;)
  196. {
  197.     swhichtile = floor (ss);
  198.     twhichtile = floor (tt);
  199.     stile = ss - swhichtile;
  200.     ttile = tt - twhichtile;
  201.  
  202.     return filteredpulsetrain (groovewidth, 1, ss+groovewidth/2, ds)
  203.              * filteredpulsetrain (grooveheight, 1, tt+grooveheight/2, dt);
  204. }
  205.  
  206.  
  207.  
  208. /* basic brick tiling pattern --
  209.  *   inputs:
  210.  *      x, y                    positions on a 2-D surface
  211.  *      tilewidth, tileheight   dimensions of each tile
  212.  *      rowstagger              how much does each row stagger relative to
  213.  *                                   the previous row
  214.  *      rowstaggervary          how much should rowstagger randomly vary
  215.  *      jaggedfreq, jaggedamp   adds noise to the edge between the tiles
  216.  *   outputs:
  217.  *      row, column             index which tile the sample is in
  218.  *      xtile, ytile            position within this tile (0-1)
  219.  */
  220. void basicbrick (float x, y;
  221.         uniform float tilewidth, tileheight;
  222.         uniform float rowstagger, rowstaggervary;
  223.         uniform float jaggedfreq, jaggedamp;
  224.         output float column, row;
  225.         output float xtile, ytile;
  226.     )
  227. {
  228.     point PP;
  229.     float scoord = x, tcoord = y;
  230.  
  231.     if (jaggedamp != 0.0) {
  232.     /* Make the shapes of the bricks vary just a bit */
  233.     PP = point noise (x*jaggedfreq/tilewidth, y*jaggedfreq/tileheight);
  234.     scoord += jaggedamp * xcomp (PP);
  235.     tcoord += jaggedamp * ycomp (PP);
  236.     }
  237.  
  238.     xtile = scoord / tilewidth;
  239.     ytile = tcoord / tileheight;
  240.     row = floor (ytile);   /* which brick row? */
  241.  
  242.     /* Shift the columns randomly by row */
  243.     xtile += mod (rowstagger * row, 1);
  244.     xtile += rowstaggervary * (noise (row+0.5) - 0.5);
  245.  
  246.     column = floor (xtile);
  247.     xtile -= column;
  248.     ytile -= row;
  249. }
  250.  
  251.  
  252.  
  253. #endif /* defined(PATTERNS_H) */
  254.